import re

import jwt
from django.contrib.auth.hashers import make_password
from django.core.paginator import Paginator
from django.http import HttpResponse
from django.shortcuts import redirect
from rest_framework.response import Response
from rest_framework.views import APIView

from meiduo import settings
from utils.captcha.captcha import captcha
from utils.comm import send_message, get_redis, get_ali_object
from .ser import *


class NewAPIView(APIView):
    def post(self, request):
        data = NewsSer(data=request.data)
        if data.is_valid():
            data.save()
            return Response({'code': 200, 'msg': '添加成功'})
        else:
            print(data.errors)
            return Response({'code': '10010'})

    def get(self, request):
        news = News.objects.all()
        p = Paginator(news, 2)
        cpage = request.GET.get('page')
        newsR = p.page(cpage)
        ser = NewsSer(newsR, many=True)
        return Response({'code': 200, 'list': ser.data, 'tpage': p.num_pages})


# 注册接口
class Register(APIView):
    def post(self, request):
        username = request.data.get('username')
        # 验证用户名是否为空
        if not username:
            return Response({'code': '10010', 'msg': '用户名不能为空'})
        # 格式是否正确
        name = re.match('\w{5,10}$', username)
        if not name:
            return Response({'code': '10011'})
        # 是否唯一
        user = User.objects.filter(username=username).first()
        if user:
            return Response({'code': '10012'})
        # 验证密码是否为空
        password = request.data.get('password')
        if not password:
            return Response({'code': '10013', 'msg': '密码不能为空'})
        # 密码格式是否正确
        pd = re.match('\w{8,20}$', password)
        if not pd:
            return Response({'msg': '密码格式不对', 'code': '10014'})
        # 手机号
        mobile = request.data.get('mobile')
        # 验证用户名是否为空
        if not mobile:
            return Response({'code': '10015', 'msg': '手机号不能为空'})
        # 格式是否正确
        phone = re.match('^1[3-9]\d{9}$', mobile)
        if not phone:
            return Response({'code': '10016'})
        # 是否唯一
        sloe = User.objects.filter(mobile=mobile).first()
        if sloe:
            return Response({'code': '10017'})
        # 验证码验证newcode，redis取根据手机号
        smscode = request.data.get('smscode')
        conn = get_redis()
        code = conn.get(mobile)
        if code:
            code = str(code, encoding='utf8')
        if smscode != code:
            return Response({'code': '10018'})
        # 判断是否同意协议
        agree = request.data.get('agree')
        if not agree:
            return Response({'code': '10019'})
        # 注册功能
        request.data['password'] = make_password(request.data.get('password'))
        ser = UserSer(data=request.data)
        if ser.is_valid():
            ser.save()
            token = jwt.encode({'data': {'username': username}},
                               settings.SECRET_KEY, algorithm='HS256')

            return Response({'code': 200, 'token': token})

        return Response({'code': 200, 'msg': '注册成功'})


class AddressAPIView(APIView):
    def post(self, request):
        ser = AddressSer(data=request.data)
        if ser.is_valid():
            ser.save()
        return Response({'code': 200})


class Test(APIView):
    def get(self, request):
        # send_message('18530561795', '123', 1)
        get_redis()
        return Response('ok')


class SendSms(APIView):
    def post(self, request):
        mobile = request.data.get('mobile')
        # 验证图片验证码，通过后发信息
        uid = request.data.get('uid')
        imgcode = request.data.get('imgcode')
        conn = get_redis()
        imagecode = conn.get(uid)
        if imagecode:
            imagecode = str(imagecode, encoding='utf8')
            if imgcode.lower() == imagecode.lower():
                codesms = random.randint(1000, 9999)
                res = send_message(mobile, str(codesms), 1)
                print(codesms)
                code = 10010
                if res:
                    code = 200
                    conn = get_redis()
                    conn.setex(mobile, 60, codesms)
                return Response({'code': code})
        return Response({'code': 20020})


class CreateCaptcha(APIView):
    def get(self, request):
        uuid = request.GET.get('uuid')
        name, text, img = captcha.generate_captcha()
        conn = get_redis()
        conn.set(uuid, text)
        return HttpResponse(img, content_type='image/jpg')


class areaM(APIView):
    def get(self, request):
        pid = request.data.get('pid')
        if not pid:
            areas = Area.objects.filter(parent_id__isnull=True).all()
        else:
            areas = Area.objects.filter(parent_id=pid).all()
        ser = AreaSer(areas, many=True)
        return Response({'code': 200, 'list': ser.data})


def xTree(datas):
    list = []
    tree = {}
    for i in datas:
        tree[i['id']] = i

    for i in datas:
        parent = i['parent']
        if not parent:
            list.append(i)
        else:
            if 'son' not in tree[parent]:
                tree[parent]['son'] = []
            tree[parent]['son'].append(i)
    return list


# 读取首页三级分类
class Home(APIView):
    def get(self, request):
        # 读取一级
        cates = Category.objects.filter(parent_id__isnull=True).all()
        list = []
        for i in cates:
            dict = {}
            dict['id'] = i.id
            dict['name'] = i.name
            # 读取二级
            two = i.subs.all()
            twolist = []
            # 遍历二级获取三级
            for j in two:
                twodict = {}
                twodict['id'] = j.id
                twodict['name'] = j.name
                three = j.subs.all()
                ser = CateSer(three, many=True)
                twodict['subs'] = ser.data
                twolist.append(twodict)

            dict['subs'] = twolist
            list.append(dict)
        # 查询一级分类，一级下面的二级，一级下面的三级，一级下面所有的商品
        categoods = []
        for j in cates:
            dict = {}
            dict['id'] = j.id
            dict['name'] = j.name
            dict['pic'] = str(j.pic)
            two = j.subs.all()
            twoser = CateSer(two, many=True)
            dict['two'] = twoser.data
            # 获取三级
            three = Category.objects.filter(top_parent=j.id, level=3).all()
            threeser = CateSer(three, many=True)
            dict['three'] = threeser.data
            # 获取商品,排序，新品按时间倒序排，价格，销量
            sorted = request.GET.get('sorted')
            topid = request.GET.get('topid')

            goods = Goods.objects.filter(category1_id=j.id, home_show=1).all()
            if sorted:
                if int(topid) == int(j.id):
                    goods = Goods.objects.filter(category1_id=j.id, home_show=1).order_by('-' + sorted).all()

            gser = GoodsSer(goods, many=True)
            dict['goods'] = gser.data
            categoods.append(dict)
        return Response({"code": 200, 'catelist': list, 'categoods': categoods})


class GoodsM(APIView):
    def get(self, request):
        id = request.GET.get('id')
        good = Goods.objects.filter(id=id).first()
        ser = GoodsSer(good)
        return Response({"code": 200, 'good': ser.data})


class GetCheckedCart(APIView):
    def get(self, request):
        # 获取userid
        userid = request.GET.get('userid')
        # 通过userid,is_checked=true查询
        cart = OrderDetail.objects.filter(user_id=userid, is_checked=True).all()
        ser = OrderDetailSer(cart, many=True)
        total = 0
        tmoney = 0
        for i in ser.data:
            # 查询总数量
            total += i['number']
            # 查询总金额
            tmoney += i['number'] * float(i['goods']['price'])
        # 返回结果
        return Response({"code": 200, 'list': ser.data, 'total': total, 'tmoney': tmoney})


import datetime
import random
from django.db import transaction


# 生成订单接口
class CreateOrders(APIView):
    @transaction.atomic
    def post(self, request):
        # 获取userid
        userid = request.data.get('userid')
        address_id = request.data.get('address_id')
        pay_method = request.data.get('pay_method')
        # 根据userid查询购物车中已经选中的记录
        cart = OrderDetail.objects.filter(user_id=userid, is_checked=True).all()
        cartser = OrderDetailSer(cart, many=True)
        # 遍历购物车
        total_amount = 0
        for i in cartser.data:
            total_amount += i['number'] * float(i['goods']['price'])
        # 生成订单号
        order_no = datetime.datetime.strftime(datetime.datetime.now(), '%Y%m%d%H%m%s') + str(userid) + str(
            random.randint(1000, 9999))
        # 查找地址构造地址信息
        add = Address.objects.filter(id=address_id).first()
        addressSer = OrderDetailSer(add)
        address = addressSer.data
        addressStr = address['province'] + ' ' + address['city'] + ' ' + address['area'] + ' ' + address[
            'address'] + ' ' + address['receive'] + ' ' + address['mobile']

        datam = {'order_no': order_no, 'user': userid, 'address': addressStr, 'total_amount': total_amount,
                 'pay_method': pay_method}
        # 创建事务结点
        sid = transaction.savepoint()
        try:
            # 调用序列化器添加订单
            ser = OrderDetailSer(data=datam)
            if ser.is_valid():
                ser.save()
                # 生成订单详情
                for i in cartser.data:
                    detaildata = {'order': order_no, 'goods': i['goods']['id'], 'goodsname': i['goods']['name'],
                                  'images': i['goods']['pic'], 'count': i['number'],
                                  'price': float(i['goods']['price']), 'user': userid}
                    # 调用序列化器添加订单详情
                    dser = OrderDetailSer(data=detaildata)
                    if dser.is_valid():
                        dser.save()
            # 购物车删除已经生成订单的记录
            OrderDetail.objects.filter(user_id=userid, is_checked=True).delete()
            # 提交事务
            transaction.savepoint_commit(sid)
            # 返回结果
            return Response({'code': 200, 'order_no': order_no, 'tmoney': total_amount})
        except:
            # 事务回滚
            transaction.savepoint_rollback(sid)
            return Response({'code': 20010})


import time


class Pay(APIView):
    def get(self, request):
        alipay = get_ali_object()

        # 生成支付的url
        query_params = alipay.direct_pay(
            subject="test",  # 商品简单描述
            out_trade_no="myorder" + str(time.time()),  # 用户购买的商品订单号（每次不一样） 20180301073422891
            total_amount=100,  # 交易金额(单位: 元 保留俩位小数)
        )
        pay_url = "https://openapi.alipaydev.com/gateway.do?{0}".format(query_params)  # 支付宝网关地址（沙箱应用）
        return redirect(pay_url)


# 支付宝回调
class Notify(APIView):
    @transaction.atomic
    def get(self, request):
        # 订单号
        out_trade_no = request.GET.get('out_trade_no')
        # 支付宝的流水号
        trade_no = request.GET.get('trade_no')
        # 根据订单号查询订单
        orderinfo = OrderInfo.objects.filter(order_no=out_trade_no).first()
        sid = transaction.savepoint()
        try:
            if orderinfo and orderinfo.status == 1:
                # 订单的支付状态，是1
                # 支付成功后，更新订单状态
                orderinfo.status = 2
                orderinfo.transaction_no = trade_no
                orderinfo.save()
                # 查询订单详情，更新库存和销量
                # print(orderinfo.details)
                details = OrderDetail.objects.filter(order_id=out_trade_no).all()
                for i in details:
                    goods = Goods.objects.filter(id=i.goods_id).first()
                    goods.sales += i.count
                    goods.store -= i.count
                    goods.save()
            transaction.savepoint_commit(sid)
            return Response({'code': 200})
        except:
            transaction.savepoint_rollback(sid)
            return Response({'code': 40020})


class CommentM(APIView):
    def post(self, request):
        ser = CommentSer(data=request.data)
        orderno = request.data.get('orderno')
        gid = request.data.get('goods')
        if ser.is_valid():
            ser.save()
            # 评价成功后更新订单详情表，订单表，商品表
            detail = OrderDetail.objects.filter(order_id=orderno, goods_id=gid).first()
            detail.status = True
            detail.save()
            # 更新订单
            d1 = OrderDetail.objects.filter(order_id=orderno, status=False).first()
            if not d1:
                info = OrderInfo.objects.filter(order_no=orderno).first()
                info.status = 5
                info.save()
            # 更新商品
            goods = Goods.objects.filter(id=gid).first()
            goods.comments += 1
            goods.save()

            return Response({"code": 200})
        else:
            return Response({"code": 20010})
